import Food from './Food'
import Snake from './Snake'
import ScorePanel from './ScorePanel'

export default class GameControl {
    // 食物
    food: Food;
    // 蛇
    snake: Snake;
    // 记分板
    scorePanel: ScorePanel;
    // 初始移动速度
    private initSpeed: number = 300
    // 每次升级提升的速度
    private liftSpeed: number = 30
    // 游戏状态
    isLive: boolean = true

    constructor() {
        // 创建一个食物对象
        this.food = new Food()
        // 创建一个蛇对象
        this.snake = new Snake()
        // 创建一个记分板对象
        this.scorePanel = new ScorePanel()
        // 调用游戏初始化方法
        this.init()
    }

    // 游戏初始化方法
    init() {
        // 绑定键盘点击事件
        document.addEventListener('keydown', this.onKeyDown.bind(this))
        // 调用让蛇移动的方法
        this.snakeMovement()
    }

    // 处理函数，当箭头方向键按下时触发
    onKeyDown(event: KeyboardEvent) {
        // 更新蛇的移动方向
        this.snake.direction = event.key
    }

    // 让蛇移动的方法
    snakeMovement() {
        // 获取蛇现在的坐标
        let X = this.snake.X
        let Y = this.snake.Y

        switch (this.snake.direction) {
            // 兼容chorm和ie
            case 'ArrowUp' || 'Up':
                // 向上移动
                Y -= this.snake.step
                break;
            case 'ArrowDown' || 'Down':
                // 向下移动
                Y += this.snake.step
                break;
            case 'ArrowLeft' || 'Left':
                // 向左移动
                X -= this.snake.step
                break;
            case 'ArrowRight' || 'Right':
                // 向右移动
                X += this.snake.step
                break;
        }

        // 检查蛇是否有触碰到食物
        this.checkSnakeAndFood(X, Y)

        try {
            // 更新蛇的坐标
            this.snake.X = X
            this.snake.Y = Y
        } catch (error) {
            const message = (<Error>error).message
            // 如果蛇触碰舞台边界,则提示用户
            alert(message)
            // 更新游戏状态
            this.isLive = false
        }
        // 通过当前等级计算出当前移动速度(初始速度 - (当前等级 - 1) * 每次升级提升的速度 )
        const currentSpeed = this.initSpeed - (this.scorePanel.level - 1) * this.liftSpeed
        // 开启定时器，让蛇持续移动
        this.isLive && setTimeout(this.snakeMovement.bind(this), currentSpeed);
    }

    // 检查蛇是否有触碰到食物
    checkSnakeAndFood(snakeX: number, snakeY: number) {
        // 如果蛇有触碰到食物
        if (snakeX === this.food.X && snakeY === this.food.Y) {
            // 调用修改食物位置的方法
            this.food.changePosition()
            // 调用添加分数的方法
            this.scorePanel.addScore()
            // 调用添加蛇身体长度的方法
            this.snake.addBody()
        }
    }
}